package com.dims_hsrc.web.controller.data;

import java.util.List;
import java.util.Map;
import java.io.File;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.ResourceAccessException;
import org.springframework.web.multipart.MultipartFile;

import com.dims_hsrc.common.core.controller.BaseController;
import com.dims_hsrc.common.core.domain.AjaxResult;
import com.dims_hsrc.common.utils.StringUtils;
import com.dims_hsrc.data.service.impl.LlmService;
import com.dims_hsrc.data.service.impl.LlmService.CustomStandard;
import com.dims_hsrc.common.config.DimsHsrcConfig;
import com.dims_hsrc.common.utils.file.FileUploadUtils;


/**
 * 大模型API调用Controller
 *
 * @author 赵浩然
 * @date 2023-05-15
 */
@RestController
@RequestMapping("/data/llm")
public class DataLLMController extends BaseController {

    private static final Logger log = LoggerFactory.getLogger(DataLLMController.class);

    @Autowired
    private LlmService llmService;

    /**
     * 从文本提取需求
     */
    @PostMapping("/extract-requirements-text")
    public AjaxResult extractRequirementsFromText(@RequestBody Map<String, String> params) {
        String content = params.get("content");
        if (StringUtils.isEmpty(content)) {
            return AjaxResult.error("内容不能为空");
        }

        try {
            if (content.length() > 30000) {
                log.warn("文本内容过长 ({} 字符)，可能导致处理缓慢", content.length());
                return AjaxResult.error("文本内容过长，请尝试减少内容或分段处理");
            }
            
            log.info("开始从文本提取需求，内容长度: {} 字符", content.length());
            List<Map<String, Object>> results = llmService.extractRequirements(content);
            log.info("文本需求提取完成，共 {} 条需求", results.size());
            return AjaxResult.success(results);
        } catch (ResourceAccessException e) {
            log.error("API请求超时", e);
            return AjaxResult.error("API请求超时，请尝试减少文本内容或分段处理: " + e.getMessage());
        } catch (Exception e) {
            log.error("提取需求失败", e);
            return AjaxResult.error("提取需求失败: " + e.getMessage());
        }
    }

    /**
     * 从文件提取需求 (通过文件名)
     */
    @PostMapping("/extract-requirements-by-name")
    public AjaxResult extractRequirementsFromFileName(@RequestBody Map<String, String> params) {
        String fileName = params.get("fileName");
        if (StringUtils.isEmpty(fileName)) {
            return AjaxResult.error("文件名不能为空");
        }

        // 验证文件类型，只允许TXT文件
        if (!fileName.toLowerCase().endsWith(".txt")) {
            log.error("文件扩展名不是TXT: {}", fileName);
            return AjaxResult.error("只支持处理TXT文本文件");
        }

        try {
            log.info("开始从文件提取需求，原始文件名: {}", fileName);
            
            // 构建文件的完整物理路径
            String uploadDir = DimsHsrcConfig.getProfile();
            String filePath;
            
            // 检查文件名是否包含完整路径
            if (fileName.startsWith("/profile")) {
                // 处理以/profile开头的路径
                filePath = uploadDir + fileName.substring("/profile".length());
            } else if (fileName.contains("/upload/")) {
                // 处理包含/upload/的相对路径
                filePath = uploadDir + "/" + fileName;
            } else {
                // 默认假设在upload目录下
                filePath = uploadDir + "/upload/" + fileName;
            }

            log.info("尝试查找文件，完整路径: {}", filePath);
            File file = new File(filePath);
            
            if (!file.exists()) {
                log.error("文件不存在: {}", filePath);
                return AjaxResult.error("文件不存在: " + fileName);
            }
            
            log.info("文件存在，准备读取: {}", file.getAbsolutePath());
            
            // 获取文件大小
            long fileSize = file.length();
            log.info("文件大小: {} 字节", fileSize);
            
            // 检查文件大小
            if (fileSize > 5 * 1024 * 1024) { // 5MB
                log.warn("文件过大 ({} MB)，可能导致处理缓慢", fileSize / (1024 * 1024));
                return AjaxResult.error("文件过大，请上传小于5MB的文件");
            }
            
            // 读取文件内容
            String fileContent;
            try {
                fileContent = new String(Files.readAllBytes(Paths.get(file.getAbsolutePath())), StandardCharsets.UTF_8);
                log.info("成功读取文件内容，字符数: {}", fileContent.length());
            } catch (Exception e) {
                log.error("读取文件内容失败", e);
                return AjaxResult.error("读取文件内容失败: " + e.getMessage());
            }
            
            if (StringUtils.isEmpty(fileContent)) {
                log.warn("文件内容为空");
                return AjaxResult.error("文件内容为空或无法解析");
            }
            
            log.info("文件内容读取成功，长度: {} 字符", fileContent.length());
            log.info("开始调用LLM处理");
            
            try {
                List<Map<String, Object>> results = llmService.extractRequirements(fileContent);
                log.info("LLM处理完成，共提取 {} 条需求", results.size());
                return AjaxResult.success(results);
            } catch (ResourceAccessException e) {
                log.error("LLM API请求超时", e);
                return AjaxResult.error("API请求超时，请尝试上传较小的文件: " + e.getMessage());
            } catch (Exception e) {
                log.error("LLM处理失败", e);
                return AjaxResult.error("大模型处理失败: " + e.getMessage());
            }
        } catch (Exception e) {
            log.error("从文件提取需求失败", e);
            return AjaxResult.error("从文件提取需求失败: " + e.getMessage());
        }
    }
    
    /**
     * 从文件提取需求 (直接上传文件)
     */
    @PostMapping("/extract-requirements")
    public AjaxResult extractRequirementsFromFile(@RequestParam("file") MultipartFile file) {
        if (file == null || file.isEmpty()) {
            return AjaxResult.error("请选择要上传的文件");
        }

        try {
            String originalFilename = file.getOriginalFilename();
            log.info("开始从上传的文件提取需求，原始文件名: {}", originalFilename);
            
            // 验证文件类型，只允许TXT文件
            String contentType = file.getContentType();
            if (contentType == null || !contentType.equals("text/plain")) {
                log.error("不支持的文件类型: {}", contentType);
                return AjaxResult.error("只支持上传TXT文本文件");
            }
        
            // 验证文件扩展名
            if (originalFilename != null && !originalFilename.toLowerCase().endsWith(".txt")) {
                log.error("文件扩展名不是TXT: {}", originalFilename);
                return AjaxResult.error("只支持上传TXT文本文件");
            }
            
            // 获取文件大小
            long fileSize = file.getSize();
            log.info("文件大小: {} 字节", fileSize);
            
            // 检查文件大小
            if (fileSize > 5 * 1024 * 1024) { // 5MB
                log.warn("文件过大 ({} MB)，可能导致处理缓慢", fileSize / (1024 * 1024));
                return AjaxResult.error("文件过大，请上传小于5MB的文件");
            }
            
            // 读取文件内容
            String fileContent;
            try {
                fileContent = new String(file.getBytes(), StandardCharsets.UTF_8);
                log.info("成功读取文件内容，字符数: {}", fileContent.length());
            } catch (Exception e) {
                log.error("读取文件内容失败", e);
                return AjaxResult.error("读取文件内容失败: " + e.getMessage());
            }
            
            if (StringUtils.isEmpty(fileContent)) {
                log.warn("文件内容为空");
                return AjaxResult.error("文件内容为空或无法解析");
            }
            
            log.info("文件内容读取成功，长度: {} 字符", fileContent.length());
            log.info("开始调用LLM处理");
            
            try {
                List<Map<String, Object>> results = llmService.extractRequirements(fileContent);
                log.info("LLM处理完成，共提取 {} 条需求", results.size());
                return AjaxResult.success(results);
            } catch (ResourceAccessException e) {
                log.error("LLM API请求超时", e);
                return AjaxResult.error("API请求超时，请尝试上传较小的文件: " + e.getMessage());
            } catch (Exception e) {
                log.error("LLM处理失败", e);
                return AjaxResult.error("大模型处理失败: " + e.getMessage());
            }
        } catch (Exception e) {
            log.error("从文件提取需求失败", e);
            return AjaxResult.error("从文件提取需求失败: " + e.getMessage());
        }
    }
    
    /**
     * 检查非标技术指标并生成风险评估报告
     */
    @PostMapping("/check-non-standard-indicators")
    public AjaxResult checkNonStandardIndicators(@RequestBody Map<String, Object> params) {
        try {
            // 获取参数
            String componentName = (String) params.get("componentName");
            String standardCode = (String) params.get("standardCode");
            List<Map<String, Object>> indicators = (List<Map<String, Object>>) params.get("indicators");
            
            if (StringUtils.isEmpty(componentName) || StringUtils.isEmpty(standardCode) || indicators == null || indicators.isEmpty()) {
                return AjaxResult.error("参数不完整，请提供组件名称、标准代码和技术指标");
            }
            
            log.info("开始检查非标技术指标, 组件名称: {}, 标准代码: {}, 指标数量: {}", componentName, standardCode, indicators.size());
            
            // 调用LlmService检查非标技术指标
            Map<String, Object> result = llmService.checkNonStandardIndicators(componentName, standardCode, indicators);
            
            log.info("非标技术指标检查完成，生成风险评估报告");
            return AjaxResult.success(result);
            
        } catch (ResourceAccessException e) {
            log.error("API请求超时", e);
            return AjaxResult.error("API请求超时，请稍后重试: " + e.getMessage());
        } catch (Exception e) {
            log.error("检查非标技术指标失败", e);
            return AjaxResult.error("检查非标技术指标失败: " + e.getMessage());
        }
    }

    /**
     * 上传自定义企业标准文档（直接提供文本内容）
     */
    @PostMapping("/upload-custom-standard-text")
    public AjaxResult uploadCustomStandardText(@RequestBody Map<String, String> params) {
        String standardName = params.get("standardName");
        String content = params.get("content");
        
        if (StringUtils.isEmpty(standardName)) {
            return AjaxResult.error("标准名称不能为空");
        }
        
        if (StringUtils.isEmpty(content)) {
            return AjaxResult.error("标准内容不能为空");
        }

        try {
            log.info("开始上传自定义企业标准文档，标准名称: {}, 内容长度: {} 字符", standardName, content.length());
            
            // 检查内容大小
            if (content.length() > 1024 * 1024) { // 大约1MB的文本
                log.warn("标准内容过大 ({} 字符)，可能导致处理缓慢", content.length());
                return AjaxResult.error("标准内容过大，请上传小于1MB的文本内容");
            }
            
            // 调用服务处理自定义标准
            CustomStandard standard = llmService.uploadCustomStandardText(standardName, content);
            
            // 构建响应数据
            Map<String, Object> responseData = new HashMap<>();
            responseData.put("id", standard.getId());
            responseData.put("name", standard.getName());
            responseData.put("fileSize", standard.getContent().length());
            responseData.put("uploadTime", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(standard.getUploadTime()));
            
            if (standard.getRequirements() != null) {
                responseData.put("requirementsCount", standard.getRequirements().size());
            } else {
                responseData.put("requirementsCount", 0);
            }
            
            log.info("自定义企业标准文档上传成功，ID: {}", standard.getId());
            return AjaxResult.success("自定义企业标准文档上传成功", responseData);
            
        } catch (Exception e) {
            log.error("上传自定义企业标准文档失败", e);
            return AjaxResult.error("上传自定义企业标准文档失败: " + e.getMessage());
        }
    }
    
    /**
     * 获取自定义企业标准详情
     */
    @GetMapping("/custom-standard/{standardId}")
    public AjaxResult getCustomStandard(@PathVariable("standardId") String standardId) {
        try {
            if (StringUtils.isEmpty(standardId)) {
                return AjaxResult.error("标准ID不能为空");
            }
            
            log.info("获取自定义企业标准详情，ID: {}", standardId);
            
            CustomStandard standard = llmService.getCustomStandardById(standardId);
            if (standard == null) {
                log.error("未找到指定的自定义企业标准，ID: {}", standardId);
                return AjaxResult.error("未找到指定的自定义企业标准");
            }
            
            // 构建响应数据
            Map<String, Object> responseData = new HashMap<>();
            responseData.put("id", standard.getId());
            responseData.put("name", standard.getName());
            responseData.put("content", standard.getContent());
            responseData.put("fileSize", standard.getContent() != null ? standard.getContent().length() : 0);
            responseData.put("uploadTime", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(standard.getUploadTime()));
            responseData.put("status", standard.getStatus());
            
            if (standard.getRequirements() != null) {
                responseData.put("requirements", standard.getRequirements());
            }
            
            log.info("成功获取自定义企业标准详情");
            return AjaxResult.success(responseData);
            
        } catch (Exception e) {
            log.error("获取自定义企业标准详情失败", e);
            return AjaxResult.error("获取自定义企业标准详情失败: " + e.getMessage());
        }
    }
    
    /**
     * 获取所有自定义企业标准列表
     */
    @GetMapping("/custom-standards")
    public AjaxResult getCustomStandards() {
        try {
            log.info("获取所有自定义企业标准列表");
            
            List<CustomStandard> standards = llmService.getAllCustomStandards();
            
            List<Map<String, Object>> responseList = new ArrayList<>();
            for (CustomStandard standard : standards) {
                Map<String, Object> item = new HashMap<>();
                item.put("id", standard.getId());
                item.put("name", standard.getName());
                item.put("fileSize", standard.getContent() != null ? standard.getContent().length() : 0);
                item.put("uploadTime", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(standard.getUploadTime()));
                item.put("status", standard.getStatus());
                
                if (standard.getRequirements() != null) {
                    item.put("requirementsCount", standard.getRequirements().size());
                } else {
                    item.put("requirementsCount", 0);
                }
                
                responseList.add(item);
            }
            
            log.info("成功获取所有自定义企业标准列表，共 {} 条", responseList.size());
            return AjaxResult.success(responseList);
            
        } catch (Exception e) {
            log.error("获取所有自定义企业标准列表失败", e);
            return AjaxResult.error("获取所有自定义企业标准列表失败: " + e.getMessage());
        }
    }
    
    /**
     * 使用自定义企业标准检查技术指标
     */
    @PostMapping("/check-with-custom-standard")
    public AjaxResult checkWithCustomStandard(@RequestBody Map<String, Object> params) {
        try {
            // 获取参数
            String componentName = (String) params.get("componentName");
            String standardId = (String) params.get("standardId");
            List<Map<String, Object>> indicators = (List<Map<String, Object>>) params.get("indicators");
            
            if (StringUtils.isEmpty(componentName) || StringUtils.isEmpty(standardId) || indicators == null || indicators.isEmpty()) {
                return AjaxResult.error("参数不完整，请提供组件名称、自定义标准ID和技术指标");
            }
            
            log.info("开始使用自定义企业标准检查技术指标, 组件名称: {}, 标准ID: {}, 指标数量: {}", componentName, standardId, indicators.size());
            
            // 调用LlmService使用自定义标准检查技术指标
            Map<String, Object> result = llmService.checkWithCustomStandard(componentName, standardId, indicators);
            
            log.info("自定义企业标准技术指标检查完成，生成风险评估报告");
            return AjaxResult.success(result);
            
        } catch (ResourceAccessException e) {
            log.error("API请求超时", e);
            return AjaxResult.error("API请求超时，请稍后重试: " + e.getMessage());
        } catch (Exception e) {
            log.error("使用自定义企业标准检查技术指标失败", e);
            return AjaxResult.error("使用自定义企业标准检查技术指标失败: " + e.getMessage());
        }
    }
}